package com.yangtu.nearbyshop.core.corg.until;

/**
 * Created by leo on 2017/10/18.
 */

import com.yangtu.nearbyshop.core.corg.Const;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

/**
 * MD5SignUtil 加解密工具类
 */
public class MD5SignUtil {


   private final static String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;



    public static  String  genEncryptKey(int KeyLength){
        Random random = new Random();
        StringBuffer Keysb = new StringBuffer();
        for(int i = 0; i<KeyLength; i++) //生成指定位数的随机秘钥字符串
        {
            int number = random.nextInt(base.length());
            Keysb.append(base.charAt(number));
        }
        return Keysb.toString();
    }



    /**
     * BASE64 解密
     * @param key 需要解密的字符串
     * @return 字节数组
     * @throws Exception
     */
    public static byte[] decryptBase64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * BASE64 加密
     * @param key 需要加密的字节数组
     * @return 字符串
     * @throws Exception
     */
    public static String encryptBase64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /**
     * 签名字符串
     * @param text 需要签名的字符串
     * @param key 密钥
     * @param input_charset 编码格式
     * @return 签名结果
     */
    public static String sign(String text, String key, String input_charset) {
        text = text + key;
        return DigestUtils.md5Hex(getContentBytes(text, input_charset));
    }

    /**
     * 签名字符串
     * @param text 需要签名的字符串
     * @param sign 签名结果
     * @param key 密钥
     * @param input_charset 编码格式
     * @return 签名结果
     */
    public static boolean verify(String sign,String text, String key, String input_charset) {
        text = text + key;
        String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
        if(mysign.equals(sign)) {
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * @param content
     * @param charset
     * @return
     * @throws SignatureException
     * @throws UnsupportedEncodingException
     */
    private static byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
        }
    }

    /**
     * 验签键值对
     * @param dataMap 键值对
     * @param encriptkey 加密key
     * @return
     */
    public static boolean verifySign(Map<String,String> dataMap, String encriptkey){
        Map<String,String> tMap=new TreeMap<>(dataMap);
        StringBuffer buf = new StringBuffer();
        String inputSign=tMap.get(Const.CMM_PARAM_SIGN);
        for (String key : tMap.keySet()) {
            if("signType".equals(key)||"sign".equals(key)){
                continue;
            }
            if(StringUtils.isBlank(tMap.get(key))){
                continue;
            }
            buf.append(key).append("=").append((String) tMap.get(key)).append("&");
        }
        String signatureStr = buf.substring(0, buf.length() - 1);
        return MD5SignUtil.verify(inputSign,signatureStr,encriptkey,"utf-8");
    }

    /**
     * 签名键值对
     * @param dataMap 签名键值对
     * @param encriptkey 加密key
     * @return
     */
    public static String sign(Map<String,String> dataMap,String encriptkey){
        Map<String,String> tMap=new TreeMap<>(dataMap);
        StringBuffer buf = new StringBuffer();
        for (String key : tMap.keySet()) {
            if("signType".equals(key)||"sign".equals(key)){
                continue;
            }
            if(StringUtils.isBlank(tMap.get(key))){
                continue;
            }
            buf.append(key).append("=").append((String) tMap.get(key)).append("&");
        }
        if(buf.length()<1){
            return "";
        }
        String signatureStr = buf.substring(0, buf.length() - 1);
        return MD5SignUtil.sign(signatureStr,encriptkey,"utf-8");
    }

    /**
     * 签名字符串
     * @param text 需要签名的字符串
     * @param key 密钥
     * @param input_charset 编码格式
     * @return 签名结果
     */
    public static String signNew(String text, String key, String input_charset) {
        text = key + text + key;
//        System.out.println(text);
        return DigestUtils.md5Hex(getContentBytes(text, input_charset));
    }

    /**
     * 签名键值对
     * @param dataMap 签名键值对
     * @param encriptkey 加密key
     * @return
     */
    public static String signNew(Map<String,Object> dataMap,String encriptkey){
        Map<String,Object> tMap=new TreeMap(dataMap);
        StringBuffer buf = new StringBuffer();
        for (String key : tMap.keySet()) {
            if("sign".equals(key)){
                continue;
            }

            if (tMap.get(key) == null) {
                continue;
            }

            if(StringUtils.isBlank(tMap.get(key) + "")){
                continue;
            }
            buf.append(key).append(tMap.get(key));
        }
        if(buf.length()<1){
            return "";
        }
        String signatureStr = buf.substring(0, buf.length());
        return MD5SignUtil.signNew(signatureStr,encriptkey,"utf-8").toUpperCase();
    }
    public static void main(String[] args) {
       String key=genEncryptKey(32);
        System.out.println("key="+key);
       String sign= sign("中国文明",key,"utf-8");
       System.out.println("sign="+sign);
        System.out.println(verify(sign,"中国文明",key,"utf-8"));
//        Map<String, String> map = new TreeMap<>();
//        map.put("bankAccountName","n6oEMJo9hVq/i33Tv9gvDA==");
//        map.put("bankCardNo","fST88snDq9oHZEHLE0s0MRczpg7MurWenxVUW2VtDdQ=");
//        map.put("bankCode","");
//        map.put("bankNm","中国银行");
//        map.put("corgId","xft");
//        map.put("datetime","20180529102119");
//        map.put("idCard","+tq7eYLIjDBIoP2s13EUDpoOqJC9tJDBrJWNj/9A4Eo=");
//        map.put("merchantName","梁燕");
//        map.put("product","27,1,0.0050,3.00,0,0.00");
//        map.put("service","register");
//        map.put("sign","335fd4880f0d78b99950e16e4ef9892d");
//        map.put("signType","MD5");
//        map.put("telephone","/GOYBdLGVUu2JtIbDkmevg==");
//        map.put("version","1.0");
//        System.out.println(verifySign(map, "xJXjMUjyFsqjI3zlkiBeUpSyTBjbjTdi"));


    }

    /**
     * 签名键值对
     * @param dataMap 签名键值对
     * @param encriptkey 加密key
     * @return
     */
    public static String signWithKey(Map<String,String> dataMap,String encriptkey){
        Map<String,String> tMap=new TreeMap<String,String>(dataMap);
        StringBuffer buf = new StringBuffer();
        for (String key : tMap.keySet()) {
            if(StringUtils.isBlank(tMap.get(key))){
                continue;
            }
            buf.append(key).append("=").append(tMap.get(key)).append("&");
        }
        buf.append("key=").append(encriptkey);
        if(buf.length()<1){
            return "";
        }
        String signatureStr = buf.substring(0, buf.length());
        return DigestUtils.md5Hex(getContentBytes(signatureStr, "utf-8"));
    }

    /**
     * 融汇金服签名
     * @param dataMap 签名键值对
     * @param encriptkey 加密key
     * @return
     */
    public static String signRH(Map<String,String> dataMap,String encriptkey){
        Map<String,String> tMap=new LinkedHashMap<>(dataMap);
        StringBuffer buf = new StringBuffer("#");
        for (String key : tMap.keySet()) {
            if("signType".equals(key)||"sign".equals(key)){
                continue;
            }
            if(StringUtils.isBlank(tMap.get(key))){
                continue;
            }
            buf.append(tMap.get(key)).append("#");
        }
        if(buf.length()<1){
            return "";
        }
        String signatureStr = buf.substring(0, buf.length());
        return MD5SignUtil.sign(signatureStr,encriptkey,"utf-8");
    }

    /**
     * GBK签名键值对&
     * @param dataMap 签名键值对
     * @param encriptkey 加密key
     * @return
     */
    public static String signwithyu(Map<String,String> dataMap,String encriptkey){
        Map<String,String> tMap=new TreeMap<String,String>(dataMap);
        StringBuffer buf = new StringBuffer();
        for (String key : tMap.keySet()) {
            if("signType".equals(key)||"sign".equals(key)){
                continue;
            }
            if(StringUtils.isBlank(tMap.get(key))){
                continue;
            }
            buf.append(key).append("=").append((String) tMap.get(key)).append("&");
        }
        if(buf.length()<1){
            return "";
        }
        String signatureStr = buf.substring(0, buf.length());
        return MD5SignUtil.sign(signatureStr,encriptkey,"GBK");
    }
}